package variableHeader

import (
	"errors"
	"fmt"
	"gitee.com/squbirreland/imgo/mqtt/agreement/constantHeader"
	"gitee.com/squbirreland/imgo/mqtt/constant"
	"gitee.com/squbirreland/imgo/utils/byteMath"
)

// Connect VariableHeaderConnect 请求链接的可变头 固定长度为10
type Connect struct {
	//ProtocolName 协议名 6字节
	ProtocolName [6]byte
	//ProtocolLevel 协议等级 1字节
	ProtocolLevel byte
	//ConnFlag ConnectFlags 链接标志 1字节
	ConnFlag ConnectFlags
	//KeepAlive 保持链接的时间 秒单位 2字节
	KeepAlive int
	//
	headerLength int
	headerBytes  []byte
}

// ConnectFlags 链接标志
type ConnectFlags struct {
	//Reserved 保留 固定为false 0
	Reserved bool
	//CleanSession 是否清除session
	CleanSession bool
	//WillFlag 是否遗嘱
	WillFlag bool
	//WillQos QOSBit2 遗嘱qos等级
	WillQos constant.QOSBit2
	//WillRetain 是否保留遗嘱
	WillRetain bool
	//PasswordFlag 是否使用密码
	PasswordFlag bool
	//UserNameFlag 是否使用用户名
	UserNameFlag bool
}

func (c *Connect) Parse(cHeader constantHeader.ConstantHeader) error {
	c.headerLength = 10
	//ProtocolName 协议名 6字节
	pns := c.headerBytes[:6]
	var pn [6]byte
	for i := range pns {
		pn[i] = pns[i]
	}
	c.ProtocolName = pn
	//ProtocolLevel 协议等级 1字节
	c.ProtocolLevel = c.headerBytes[6]
	//ConnFlag ConnectFlags 链接标志 1字节
	connFlagBit8, err := byteMath.Byte2Str(c.headerBytes[7], 2, 8)
	if err != nil {
		return err
	}
	cf := ConnectFlags{}
	if connFlagBit8[7] == '1' {
		cf.Reserved = true
	}
	if connFlagBit8[6] == '1' {
		cf.CleanSession = true
	}
	if connFlagBit8[5] == '1' {
		cf.WillFlag = true
	}
	cfQos := connFlagBit8[3:5]
	willQos, err := byteMath.Str2Int(cfQos, 2)
	if err != nil {
		return err
	}
	cf.WillQos = constant.QOSBit2(willQos)
	if connFlagBit8[2] == '1' {
		cf.WillRetain = true
	}
	if connFlagBit8[1] == '1' {
		cf.PasswordFlag = true
	}
	if connFlagBit8[0] == '1' {
		cf.UserNameFlag = true
	}
	c.ConnFlag = cf
	//KeepAlive 保持链接的时间 秒单位 2字节
	kab := c.headerBytes[8:10]
	keepAlive, err := byteMath.Str2Int(fmt.Sprintf("%x%x", kab[0], kab[1]), 16)
	if err != nil {
		return err
	}
	c.KeepAlive = keepAlive
	c.headerBytes = c.headerBytes[:c.headerLength]
	return nil
}

func (c *Connect) CreateBytes(cHeader constantHeader.ConstantHeader) error {
	return errors.New(" this func should not to be used ! ")
}

func (c *Connect) GetLength() int {
	return c.headerLength
}

func (c *Connect) GetHeaderBytes() []byte {
	return c.headerBytes
}

func (c *Connect) SetLength(i int) {
	c.headerLength = i
}

func (c *Connect) SetHeaderBytes(b []byte) {
	c.headerBytes = b
}
